home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dc1 / toplevel.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  23KB  |  969 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  TOPLEVEL.C
  9.  */
  10.  
  11. /*
  12. **      $Filename: toplevel.c $
  13. **      $Author: dice $
  14. **      $Revision: 30.326 $
  15. **      $Date: 1995/12/24 06:09:50 $
  16. **      $Log: toplevel.c,v $
  17.  * Revision 30.326  1995/12/24  06:09:50  dice
  18.  * .
  19.  *
  20.  * Revision 30.325  1995/12/24  05:38:17  dice
  21.  * .
  22.  *
  23.  * Revision 30.6  1994/08/04  04:49:46  dice
  24.  * fixed regargs bug.  A previous fix involving automatic registerized
  25.  * arguments broke explicit registerization of arguments when more then
  26.  * four arguments are specified.
  27.  *
  28.  * Revision 30.0  1994/06/10  18:04:58  dice
  29.  * .
  30.  *
  31.  * Revision 1.14  1993/11/22  00:28:36  jtoebes
  32.  * Final cleanup to eliminate all cerror() messages with strings.
  33.  *
  34.  * Revision 1.14  1993/11/22  00:28:36  jtoebes
  35.  * Final cleanup to eliminate all cerror() messages with strings.
  36.  *
  37.  * Revision 1.13  1993/09/18  21:03:26  jtoebes
  38.  * Minor fix encountered when recursively recompiling compiler.  Previous
  39.  * fix failed to set the auto bit under some circumstances for local function
  40.  * pointers.
  41.  *
  42.  * Revision 1.12  1993/09/13  21:28:23  jtoebes
  43.  * Fixed BUG00117 - Problems with typdef'd functions.
  44.  * Made error logic ignore function pointers declared in a local procedure.
  45.  *
  46.  * Revision 1.11  1993/09/11  23:25:16  jtoebes
  47.  * Fixed BUG00047 - DC1 failes to warn about missing , in initialized expression.
  48.  * Changed to conform to new calling parameters for CompBracedAssign.
  49.  *
  50.  * Revision 1.10  1993/09/06  23:37:12  jtoebes
  51.  * Fixed BUG00102 - Constant expressions not allowed for bitfields.
  52.  *
  53.  * Revision 1.9  1993/09/06  14:10:15  jtoebes
  54.  * fixed BUG00113 - const keyword was not allowed after the type.
  55.  * Simply inserted parsing code for immediately after the type.
  56.  *
  57.  * Revision 1.8  1993/09/06  13:21:34  jtoebes
  58.  * Fixed BUG01091 - Bad error for undefined structure tag.
  59.  * Added code for arrays to ensure that structures and unions are defined
  60.  * before attempting to make an array out of them.
  61.  *
  62.  * Revision 1.7  1993/09/06  11:06:50  jtoebes
  63.  * Fixed BUG06063 - Error for initialization of an external array of chars.
  64.  * Turned off extern bit when something was initialized.
  65.  *
  66.  * Revision 1.6  1993/09/05  23:54:32  jtoebes
  67.  * Fixed BUG06045 - Enforcer hit for invalid structure definitions.
  68.  * Added code to skip over current level of nesting when too many
  69.  * initializers are given for a structure.
  70.  *
  71. **/
  72.  
  73. #include "defs.h"
  74.  
  75.  
  76. #define MAXCPX    64    /*  maximum type declarator complexity    */
  77.  
  78. static short StructLevel;   /*    sp CompVar() does not call SemanticAdd() */
  79. static ExtVarNode *ExtBase;
  80. static ExtStrNode *StrBase;
  81.  
  82. Prototype short TopLevel(short);
  83. Prototype short CompDecl(short, Var **, long);
  84. Prototype short CompType(short, Type **, long *, long *);
  85. Prototype short CompVar(short, Type *, long, long, Var **);
  86. Prototype short CompTypeDeclarators(short, Type **, Symbol **, long);
  87. Prototype short CompStructType(short, Type **, long);
  88. Prototype short CompEnumType(short, Type **);
  89. Prototype short CompTypeofType(short, Type **);
  90. Prototype short ResolveStructUnionType(Type *);
  91.  
  92. Prototype void AddExternList(Var *);
  93. Prototype void DumpExternList(long);
  94. Prototype void AddStrList(ubyte *, long, long, long);
  95. Prototype void MakeStringConst(long);
  96. Prototype void DelStrList(long);
  97. Prototype void DumpStrList(void);
  98.  
  99. Local short PointerOpt(Type **, Symbol **, short);
  100. Local short DirectDeclarator(Type **, Symbol **, short, long);
  101. Local void ReverseFeed(Type **, Type *);
  102. Local int ExplicitRegistersDeclared(Var **vars, long args);
  103.  
  104.  
  105. /*
  106.  *  TopLevel() expects:
  107.  *
  108.  *    <decl>
  109.  *    typedef <decl>
  110.  */
  111.  
  112. short
  113. TopLevel(short t)
  114. {
  115.     Var *var;
  116.     Var *nv;
  117.  
  118.     /*
  119.      *    Do not absort the semicolon at the end of the statement as this
  120.      *    would require another lexical token causing a #pragma DCCOPTS
  121.      *    after a procedure definition to be interpreted before the previous
  122.      *    procedure's code was generated.
  123.      */
  124.  
  125.     t = CompDecl(t, &var, 0);
  126.  
  127.     while (var) {
  128.     nv = var->Next;
  129.     GenerateVar(var);
  130.     var = nv;
  131.     }
  132.  
  133.     /*
  134.      *    Clear out any lingering expression structures here ??
  135.      *    Clear out all procedural sub-variables EXCEPT arguments to
  136.      *        the procedure and the procedure var itself. ??
  137.      */
  138.  
  139.     t = GetToken();
  140.  
  141.     return(t);
  142. }
  143.  
  144. short
  145. CompDecl(short t, Var **pvar, long absorbSemi)
  146. {
  147.     short typeDef = 0;        /*  preceeded by typedef    */
  148.     Var *var = NULL;
  149.     Type *baseType;
  150.     long  baseFlags;
  151.     long  regFlags;
  152.     long li = LFBase->lf_Index;
  153.  
  154.     if (t == TokTypeDef) {    /*  opt typedef     */
  155.     t = GetToken();
  156.     typeDef = 1;
  157.     }
  158.  
  159.     /*
  160.      *    type spec
  161.      */
  162.  
  163.     t = CompType(t, &baseType, &baseFlags, ®Flags);
  164.  
  165.     /*
  166.      *    list of type-qualfied variables (i.e. char *foo, the '*foo').  CompVar()
  167.      *    also parses entire subroutines and returns a pseudo ';' for them.
  168.      *
  169.      *    The variables are semantically added
  170.      */
  171.  
  172.     if (typeDef) {
  173.     t = CompVar(t, baseType, baseFlags, regFlags, NULL);
  174.     while (t == TokComma) {
  175.         t = GetToken();
  176.         t = CompVar(t, baseType, baseFlags, regFlags, NULL);
  177.     }
  178.     } else if (t != TokSemi) {
  179.     Var *vlast;
  180.     Var *v;
  181.  
  182.     t = CompVar(t, baseType, baseFlags, regFlags, &var);
  183.     vlast = var;
  184.  
  185.     /*
  186.      * Handle case where we compiled a procedure, the lexical index
  187.      * must indicate the beginning of the procedure so debugging
  188.      * info is aligned properly
  189.      */
  190.  
  191.     if (var->Type->Id == TID_PROC)
  192.         var->LexIdx = li;
  193.  
  194.     /*
  195.      * Handle list of vars
  196.      */
  197.  
  198.     while (t == TokComma) {
  199.         t = GetToken();
  200.         t = CompVar(t, baseType, baseFlags, regFlags, &v);
  201.  
  202.         vlast->Next = v;
  203.         vlast = v;
  204.     }
  205.     vlast->Next = NULL;
  206.     }
  207.     if (t != TokSemi) {
  208.     zerror(EWARN_EXPECTED_SEMICOLON);
  209.     if (LFBase->lf_Index == li)
  210.         t = GetToken();
  211.     }
  212.  
  213.     if (absorbSemi)
  214.     t = GetToken();
  215.  
  216.     *pvar = var;
  217.     return(t);
  218. }
  219.  
  220. short
  221. CompType(short t, Type **ptype, long *pflags, long *rflags)
  222. {
  223.     Type *type;
  224.     long  flags = 0;
  225.  
  226.     *rflags = 0;
  227.  
  228.     /*
  229.      *    Allow register qualifiers before or after type qualifiers for
  230.      *    SAS/C compatibility.  Personally, DICE likes them before
  231.      */
  232.  
  233.     while (t == TokTypeQual) {
  234.     flags |= (long)LexData;
  235.     t = GetToken();
  236.     }
  237.     while (t == TokRegQual) {
  238.     if (*rflags)
  239.         zerror(EERROR_ILLEGAL_REGSPEC);
  240.     else
  241.         *rflags = (long)LexData | RF_REGISTER;
  242.     t = GetToken();
  243.     }
  244.     while (t == TokTypeQual) {
  245.     flags |= (long)LexData;
  246.     t = GetToken();
  247.     }
  248.     if (t == TokTypeId) {
  249.     type = (Type *)LexData;
  250.     t = GetToken();
  251.     while (t == TokTypeQual) {
  252.         flags |= (long)LexData;
  253.         t = GetToken();
  254.     }
  255.     if (t == TokTypeId) {
  256.         if ((Type *)LexData == &LongType && (type == &ShortType || type == &LongType)) {
  257.         t = GetToken();
  258.         } else if ((Type *)LexData == &DoubleType && type == &LongType) {
  259.         type = &LongDoubleType;
  260.         t = GetToken();
  261.         }
  262.         /* note, can't else error since structure elements may
  263.          * be type names
  264.          */
  265.     }
  266.     } else if (t == TokStruct || t == TokUnion) {
  267.     t = CompStructType(t, &type, flags);
  268.     } else if (t == TokEnum) {
  269.     t = CompEnumType(t, &type);
  270.     } else if (t == TokTypeof) {
  271.     t = CompTypeofType(t, &type);
  272.     } else {
  273.     type = &LongType;
  274.     }
  275.  
  276.     flags |= type->Flags;
  277.  
  278.     while (t == TokTypeQual && ((long)LexData & TF_STORQUALMASK)) {
  279.     /*
  280.      *  Generate warning, but accept type.    Note that the qualifier
  281.      *  will apply to ALL declarations in this statement rather then
  282.      *  just the first as in SAS/C, thus the warning.
  283.      */
  284.     zerror(EWARN_SASC_QUALIFIER_PLACEMENT);
  285.     flags |= (long)LexData;
  286.     t = GetToken();
  287.     }
  288.  
  289.     if ((type->Flags & TF_TYPEQUALMASK) != (flags & TF_TYPEQUALMASK))
  290.     type = TypeToQualdType(type, flags & TF_TYPEQUALMASK);
  291.  
  292.     *ptype = type;
  293.     *pflags= flags & TF_STORQUALMASK;
  294.  
  295.     return(t);
  296. }
  297.  
  298. /*
  299.  *  Compile a variable... handle *, [], (), etc...  void (*ptr)()
  300.  *             also handle '= expression'
  301.  *             also handle bit fields though currently they are
  302.  *             NOT implemented properly.
  303.  *
  304.  *  if pvar == NULL then we are compiling a typedef.  Return TokSemi for
  305.  *  procedural declarations that end with '}'.
  306.  *
  307.  *  baseType->Flags holds TYPEQUALMASK flags while
  308.  *  storFlags        holds STORQUALMASK flags.
  309.  */
  310.  
  311. short
  312. CompVar(short t, Type *baseType, long storFlags, long regFlags, Var **pvar)
  313. {
  314.     Var *var = NULL;
  315.     Type *type;
  316.     Symbol *sym = NULL;
  317.     long extraTypeFlags = 0;    /*  propogated through override */
  318.     short protoVoid = 0;
  319.  
  320.     /*
  321.      *    step 1, parse the name .. get the name symbol and representitive type
  322.      */
  323.  
  324.     type = baseType;
  325.  
  326.     t = CompTypeDeclarators(t, &type, &sym, storFlags);
  327.  
  328.     if (type->Flags & TF_STKCALL) storFlags &= ~TF_REGCALL;
  329.  
  330.     if (t == TokColon) {
  331.     long bits;
  332.     Exp *exp = NULL;
  333.  
  334.     if (StructLevel == 0)
  335.         zerror(EERROR_ILLEGAL_BITFIELD_OP);
  336.  
  337.     if (type->Id != TID_INT || (type->Size != 4 && type->Size != 2))
  338.         zerror(EERROR_ILLEGAL_BITFIELD_OP);
  339.  
  340.     t = GetToken();
  341.     t = CompExp(t, &exp, 0);
  342.     bits = ExpToConstant(exp);
  343.  
  344.     if (bits > 32 || bits < 0) {
  345.         zerror(EERROR_ILLEGAL_BITFIELD_OP);
  346.         bits = 32;
  347.     }
  348.     type = MakeBitfieldType(type->Flags & TF_UNSIGNED, bits);
  349.     }
  350.  
  351.     /*
  352.      *    Create final type that includes storage qualifiers.
  353.      */
  354.  
  355.     if ((storFlags & TF_STORNOTLOCAL) == 0 && State != SOUTSIDE)
  356.     {
  357.         /* Check to see that this is a pointer to a function */
  358.         if (type->Id != TID_PTR   ||
  359.             type->SubType == NULL ||
  360.             type->SubType->Id != TID_PROC)
  361.         {
  362.         if (storFlags & TF_AUTOILLEGAL)
  363.         zerror(EERROR_ILLEGAL_QUALIFIER);
  364.     }
  365.     storFlags |= TF_AUTO;
  366.     }
  367.  
  368.     {
  369.     long tflags = (type->Flags | storFlags) & ~TF_NOTINTYPE;
  370.  
  371.     if (type->Flags != tflags)
  372.         type = TypeToQualdType(type, tflags);
  373.     }
  374.  
  375.     /*
  376.      *    If typedef we stop here
  377.      */
  378.  
  379.     if (pvar == NULL) {
  380.     if (type->Flags != (type->Flags | storFlags))
  381.         type = TypeToQualdType(type, type->Flags | storFlags);
  382.  
  383.     if (t != TokSemi && t != TokComma)
  384.         zerror(EERROR_ILLEGAL_TYPEDEF);
  385.     if (sym)
  386.         SemanticAdd(sym, TokTypeId, type);
  387.     else
  388.         zerror(EERROR_ILLEGAL_TYPEDEF);
  389.     return(t);
  390.     }
  391.  
  392.     /*
  393.      *    definitely a variable.    Check for overide of previous def
  394.      *    in this block level, or global block level if not auto.
  395.      *
  396.      *    STATIC VARIABLES inside subroutines are special, they do not bother
  397.      *    global variables outside subroutines of the same name.
  398.      *
  399.      *    check opt '= exp' and optional code if a procedure
  400.      */
  401.  
  402.     if (sym == NULL)
  403.     {
  404.     /* Well, we have a syntax error */
  405.     zerror(EERROR_SYNTAX_ERROR_DECL);
  406.     sym = MakeSymbol("<PHONEYSYM>", 11, LFBase->lf_Index, NULL);
  407.     storFlags |= VF_DECLD;
  408.     }
  409.  
  410.     if (StructLevel == 0 && (var = BlockRemoveDuplicateVar(storFlags, sym, type))) {
  411.     extraTypeFlags = (var->Type->Flags | storFlags) & TF_KEEPPROC;
  412.     if (var->Type->Args == 0)   /*    proto was ... foo(void) */
  413.         protoVoid = 1;
  414.  
  415.     if ((type->Flags & TF_KEEPPROC) != (extraTypeFlags & TF_KEEPPROC))
  416.         type = TypeToQualdType(type, type->Flags | extraTypeFlags);
  417.     }
  418.  
  419.     if (var == NULL) {
  420.     if (StructLevel == 0 && State != SOUTSIDE && (storFlags & TF_STORNOTLOCAL) == 0 && type->Id != TID_PROC) {
  421.         var = AllocTmpStructure(Var);   /*    does not survive subroutine */
  422.     } else {
  423.         var = AllocStructure(Var);        /*    permanent   */
  424.     }
  425.     if (sym && StructLevel == 0) {
  426.         if (type->Id == TID_PROC || (storFlags & TF_EXTERN))
  427.         SemanticAddTop(sym, TokVarId, var);
  428.         else
  429.         SemanticAdd(sym, TokVarId, var);
  430.     }
  431.     }
  432.  
  433.     var->Type = type;
  434.     var->Sym  = sym;
  435.     var->LexIdx = LFBase->lf_Index;
  436.  
  437.     if (storFlags & TF_REGISTER)
  438.     ++var->Refs;
  439.  
  440.     if ((type->Id == TID_STRUCT || type->Id == TID_UNION) && (type->Size == 0))
  441.     {
  442.     Undefined_Tag(type, sym, LFBase->lf_Index);
  443.     }
  444.  
  445.     *pvar = var;
  446.  
  447.     if (State == SOUTSIDE && (storFlags & TF_AUTO))
  448.     zerror(EERROR_ILLEGAL_QUALIFIER);
  449.  
  450.     var->Flags = type->Flags | storFlags | extraTypeFlags | (var->Flags & VF_DECLD);
  451.     var->RegFlags = regFlags;
  452.  
  453. #ifdef DYNAMIC
  454.     if ((var->Flags & (TF_EXTERN|TF_DYNAMIC)) == TF_DYNAMIC) {
  455.     var->Type = type = TypeToPtrType(var->Type);
  456.     asm_dynamictag(var);
  457.     }
  458. #endif
  459.     if (type->Id == TID_PROC) {
  460.     if (t != TokSemi && t != TokComma) {    /*  definition    */
  461.         var->Flags &= ~(VF_DECLD | TF_EXTERN);
  462.  
  463.         /*
  464.          *    if not a prototyped procedure must munge arguments properly.
  465.          *    This applies to floats, for example, which are really doubles
  466.          *    for non-prototyped procedures.
  467.          */
  468.  
  469.         if ((type->Flags & TF_PROTOTYPE) == 0) {
  470.         short i;
  471.         for (i = 0; i < type->Args; ++i) {
  472.             Type **t2 = &type->Vars[i]->Type;
  473.             *t2 = ActualArgType(*t2);
  474.         }
  475.         }
  476.  
  477.         /*
  478.          *    munge routine prototyped as foo(void) but declared foo()
  479.          */
  480.  
  481.         if (protoVoid && type->Args < 0)
  482.         var->Type = type = TypeToProcType(type->SubType, NULL, 0, type->Flags | TF_PROTOTYPE);
  483.  
  484.         if (var->u.Block && !(var->Flags & TF_STATIC))
  485.         zerror(EERROR_MULTIPLY_DEFINED_PROC);
  486.  
  487.         t = CompProcedure(t, var);
  488.  
  489.     } else {
  490.         if (var->u.Block == NULL) {
  491.         if (!(var->Flags & TF_STATIC))
  492.             var->Flags |= TF_EXTERN;
  493.         } else {
  494.         zerror(EERROR_MULTIPLY_DEFINED_PROC);
  495.         }
  496.  
  497.         /*
  498.          *    Generate Register Specification Output Data
  499.          */
  500.  
  501.         if (RegSpecOutputOpt)
  502.         GenerateRegSpecOutput(var);
  503.     }
  504.     } else {
  505.     if (t == TokEq) {    /*  assigned expression */
  506.         Exp *exp;
  507.  
  508.             /* Any assignment to a global variable will eliminate the extern */
  509.             /* portion of the symbol.  This is in accordance to ANSI.        */
  510.         var->Flags &= ~TF_EXTERN;
  511.  
  512.         if (StructLevel)
  513.         zerror(EERROR_ILLEGAL_ASSIGNMENT);
  514.  
  515.         t = GetToken();
  516.         if (t == TokLBrace)
  517.         {
  518.         t = CompBracedAssign(GetToken(), var->Type, &exp, 1, sym);
  519.         if (t != TokRBrace)
  520.         {
  521.             zerror(EERROR_TOO_MANY_INITIALIZERS);
  522.             t = match_nesting(t);
  523.         }
  524.         t = GetToken();
  525.         }
  526.         else if (t == TokStrConst && var->Type->Id == TID_ARY)
  527.         {
  528.         t = CompBracedAssign(t, var->Type, &exp, 0, sym);
  529.             }
  530.         else if ((var->Flags & TF_AUTO) == 0)
  531.         {
  532.         t = CompBracedAssign(t, var->Type, &exp, 0, sym);
  533.         } else
  534.         {
  535.            /* If we get here, we know that the TF_AUTO bit is on.  If  */
  536.            /* the TF_STATIC flag is also set, this should be diagnosed */
  537.            /* This logic used to be in the previous test, but since it */
  538.            /* really can never occur, we moved it down here and expect */
  539.            /* to take it out after the beta.                           */
  540.            /* Note that the assignment code will be pulled out by the  */
  541.            /* block code in stmt.c (only simple assignments)           */
  542.             if (var->Flags & TF_STATIC)
  543.             {
  544.                   dbprintf(("Unexpected Type %ld\n", var->Flags));
  545.                Assert(0);
  546.             }
  547.            t = CompExp(t, &exp, 0);
  548.             }
  549.         var->u.AssExp = exp;
  550.     }
  551.     }
  552.     return(t);
  553. }
  554.  
  555. /*
  556.  *  abstract:
  557.  *    PTR
  558.  *    PTRopt direct
  559.  *
  560.  *  direct:
  561.  *    (abstract)
  562.  *    DIRECTopt [constant-exp]
  563.  *    DIRECTopt (parameter-type-list)
  564.  *
  565.  *  storFlags might apply to some lower level type (procedure spec)
  566.  */
  567.  
  568. short
  569. CompTypeDeclarators(short t, Type **ptype, Symbol **psym, long storFlags)
  570. {
  571.     Type *head = NULL;
  572.  
  573.     /* *ptype = baseType; */
  574.  
  575.     if (t == TokStar)
  576.     t = PointerOpt(ptype, psym, t);
  577.  
  578.     switch(t) {
  579.     case TokLParen:    /*  late eval    */
  580.     head = &CharType;
  581.     t = CompTypeDeclarators(GetToken(), &head, psym, 0);
  582.     t = SkipToken(t, TokRParen);
  583.     break;
  584.     case TokVarId:    /*  symbol    */
  585.     case TokId:
  586.     case TokTypeId:
  587.     case TokEnumConst:
  588.     *psym = LexSym;
  589.     t = GetToken();
  590.     break;
  591.     /* default: break; */   /*    other    */
  592.     }
  593.  
  594.     t = DirectDeclarator(ptype, psym, t, storFlags);
  595.  
  596.     /*
  597.      *    Stick head in front of ptype.  Must scan head in reverse.
  598.      */
  599.  
  600.     if (head)
  601.     ReverseFeed(ptype, head);
  602.  
  603.     return(t);
  604. }
  605.  
  606. void
  607. ReverseFeed(ptype, type)
  608. Type **ptype;
  609. Type *type;
  610. {
  611.     if (type) {
  612.     ReverseFeed(ptype, type->SubType);
  613.  
  614.     switch(type->Id) {
  615.     case TID_INT:
  616.         break;    /*  done    */
  617.     case TID_PTR:
  618.         *ptype = TypeToPtrType(*ptype);
  619.         break;
  620.     case TID_ARY:
  621.         {
  622.         long entries = 0;
  623.  
  624.         if (type->SubType->Size)
  625.             entries = type->Size / type->SubType->Size;
  626.         *ptype = TypeToAryType(*ptype, NULL, entries);
  627.         }
  628.         break;
  629.     case TID_PROC:
  630.         *ptype = TypeToProcType(*ptype, type->Vars, type->Args, type->Flags);
  631.         break;
  632.     default:
  633.         dbprintf(("typedecl/tid %d\n", type->Id));
  634.         Assert(0);
  635.         break;
  636.     }
  637.     }
  638. }
  639.  
  640. short
  641. PointerOpt(Type **ptype, Symbol **psym, short t)
  642. {
  643.     while (t == TokStar) {
  644.     long flags = 0;
  645.  
  646.     t = GetToken();
  647.     *ptype = TypeToPtrType(*ptype);
  648.     while (t == TokTypeQual) {
  649.         flags |= (long)LexData;
  650.         t = GetToken();
  651.     }
  652.     if (flags) {
  653.         Type *type = *ptype;
  654.         *ptype = TypeToQualdType(type, (flags | type->Flags) & TF_TYPEQUALMASK);
  655.     }
  656.     }
  657.     return(t);
  658. }
  659.  
  660. short
  661. DirectDeclarator(Type **ptype, Symbol **psym, short t, long storFlags)
  662. {
  663.     switch(t) {
  664.     case TokLParen:
  665.     {
  666.         Var **vars;
  667.         long args;
  668.         long flags;
  669.         t = CompProcedureArgDeclarators(GetToken(), &vars, &args, &flags);
  670.  
  671.         t = DirectDeclarator(ptype, psym, t, 0);
  672.  
  673.         /*
  674.          *    Finish up.  If procedure is not already registerized determine
  675.          *    whether to make it so or not.  (flags & TF_STKCALL) is set when
  676.          *    automatic registerization is not possible, (storFlags & TF_STKCALL)
  677.          *    when the user explicitly does not want automatic registerization
  678.          *
  679.          *  If explicit registers have been declared, do NOT set 
  680.          *  TF_STKCALL.
  681.          */
  682.  
  683.         if (args <= 0 || args > 4) {
  684.             if (ExplicitRegistersDeclared(vars, args) == 0)
  685.             flags |= TF_STKCALL;
  686.         }
  687.         if ((flags & TF_REGCALL) == 0)
  688.         {
  689.         if (((storFlags|flags) & TF_STKCALL) == 0 &&
  690.             (RegCallOpt || (storFlags & TF_REGCALL)) && !(flags & TF_DOTDOTDOT)
  691.               && args > 0 && args <= 4)
  692.             flags |= TF_REGCALL;
  693.         }
  694.         storFlags &= ~TF_REGCALL;
  695.  
  696.         if (flags & TF_REGCALL)
  697.         AutoAssignRegisteredArgs(vars, args);
  698.         *ptype = TypeToProcType(*ptype, vars, args, flags | storFlags);
  699.     }
  700.     break;
  701.     case TokLBracket:
  702.     {
  703.         Exp *exp = NULL;
  704.  
  705.         t = GetToken();
  706.         if (t != TokRBracket)
  707.         t = CompExp(t, &exp, 1);
  708.  
  709.         if (((*ptype)->Id == TID_STRUCT || (*ptype)->Id == TID_UNION) && ((*ptype)->Size == 0))
  710.         {
  711.         Undefined_Tag(*ptype, NULL, LFBase->lf_Index);
  712.         }
  713.  
  714.         t = SkipToken(t, TokRBracket);
  715.  
  716.         t = DirectDeclarator(ptype, psym, t, storFlags);
  717.  
  718.         if ((*ptype)->Size == 0) {
  719.         zerror(EERROR_SIZEOF_TYPE_0);
  720.         }
  721.         *ptype = TypeToAryType(*ptype, exp, 0);
  722.     }
  723.     break;
  724.     default:            /*    fix the ordering    */
  725.     break;
  726.     }
  727.     return(t);
  728. }
  729.  
  730. /*
  731.  * Scan procedure variables to determine if explicit
  732.  * registers have been declared.
  733.  */
  734.  
  735. int
  736. ExplicitRegistersDeclared(Var **vars, long args)
  737. {
  738.     long i;
  739.     int r = 0;
  740.  
  741.     for (i = 0; i < args; ++i, ++vars) {
  742.         if ((*vars)->RegFlags & RF_REGISTER) {
  743.             r = 1;
  744.             break;
  745.     }
  746.     }
  747.     return(r);
  748. }
  749.  
  750. /*
  751.  *  Access/compile a structural type that may or may not exist yet.
  752.  *
  753.  *  t == TokStruct or TokUnion.     s/u [optid] [{ structure}]
  754.  */
  755.  
  756. short
  757. CompStructType(short t, Type **ptype, long flags)
  758. {
  759.     short isUnion = (t == TokUnion);
  760.     Type *type;
  761.  
  762.     t = GetToken();
  763.     if (t == TokId || t == TokTypeId || t == TokVarId || t == TokEnumConst) {
  764.     if ((type = FindStructUnionType(LexSym, isUnion)) == NULL)
  765.         type = MakeStructUnionType(LexSym, isUnion);
  766.     t = GetToken();
  767.     } else {
  768.     type = MakeStructUnionType(NULL, isUnion);
  769.     }
  770.  
  771.     if (t == TokLBrace) {
  772.     t = ResolveStructUnionType(type);
  773.     }
  774.  
  775.     *ptype = type;
  776.     return(t);
  777. }
  778.  
  779. short
  780. ResolveStructUnionType(type)
  781. Type *type;
  782. {
  783.     short t;
  784.  
  785.     {
  786.     Var **vars = NULL;
  787.     Var *var;
  788.     short n = 0;
  789.     short siz = 0;
  790.  
  791.     t = GetToken();
  792.     ++StructLevel;
  793.     while (t && t != TokRBrace) {
  794.         t = CompDecl(t, &var, 1);
  795.         while (var) {
  796.         if (n == siz) {
  797.             siz += 4;
  798.             vars = zrealloc(vars, sizeof(Var *), n, siz);
  799.         }
  800.         vars[n++] = var;
  801.         var = var->Next;
  802.         }
  803.     }
  804.     --StructLevel;
  805.     if (siz == 0)
  806.     {
  807.         zerror(EERROR_NO_MEMBERS, SymToString(FindStructUnionTag(type)));
  808.         vars = zrealloc(vars, sizeof(Var *), 1, 1);
  809.         var = AllocStructure(Var);
  810.         var->Type = &LongType;
  811.         vars[0] = var;
  812.         n = 1;
  813.     }
  814.  
  815.     SetStructUnionType(type, vars, n, type->Flags);
  816.     if (t == TokRBrace)
  817.         t = GetToken();
  818.     }
  819.     return(t);
  820. }
  821.  
  822. /*
  823.  *  Access/compile an enum type that may or may not exist yet.
  824.  *
  825.  *  enum [enumName] [{ specifiers }]
  826.  */
  827.  
  828. short
  829. CompEnumType(short t, Type **ptype)
  830. {
  831.     Type *type;
  832.  
  833.     t = GetToken();
  834.     if (t == TokId || t == TokTypeId || t == TokVarId || t == TokEnumConst) {
  835.     if ((type = FindEnumType(LexSym)) == NULL)
  836.         type = MakeEnumType(LexSym);
  837.     t = GetToken();
  838.     } else {
  839.     type = MakeEnumType(NULL);
  840.     }
  841.     if (t == TokLBrace) {
  842.     long eval = 0;
  843.     t = GetToken();
  844.     while (t != TokRBrace) {
  845.         Symbol *sym;
  846.         if (t != TokId) {
  847.         if (t == TokVarId || t == TokTypeId) {
  848.             zerror(EWARN_ENUM_OVERIDE);
  849.         } else {
  850.             zerror(EERROR_SYNTAX_ERROR_DECL);
  851.             break;
  852.         }
  853.         }
  854.         sym = LexSym;
  855.         t = GetToken();
  856.         if (t == TokEq) {
  857.         Exp *exp;
  858.  
  859.         t = GetToken();
  860.         t = CompExp(t, &exp, 0);
  861.         eval = ExpToConstant(exp);
  862.         }
  863.         AddEnumIdent(type, sym, eval);
  864.         ++eval;
  865.         if (t == TokComma) {
  866.         t = GetToken();
  867.         } else if (t != TokRBrace) {
  868.         zerror(EERROR_SYNTAX_ERROR_DECL);
  869.         break;
  870.         }
  871.     }
  872.     if (t == TokRBrace)
  873.         t = GetToken();
  874.     }
  875.     *ptype = type;
  876.     return(t);
  877. }
  878.  
  879. /*
  880.  *  Compile typeof(exp)
  881.  */
  882.  
  883. short
  884. CompTypeofType(short t, Type **ptype)
  885. {
  886.     Exp *exp;
  887.  
  888.     t = SkipToken(GetToken(), TokLParen);
  889.     t = CompExp(t, &exp, 1);
  890.     t = SkipToken(t, TokRParen);
  891.     *ptype = ExpToType(exp);
  892.     return(t);
  893. }
  894.  
  895. void
  896. AddExternList(var)
  897. Var *var;
  898. {
  899.     ExtVarNode *evn = AllocStructure(ExtVarNode);
  900.  
  901.     evn->Next = ExtBase;
  902.     evn->Var = var;
  903.     ExtBase = evn;
  904. }
  905.  
  906. void
  907. DumpExternList(long procs)
  908. {
  909.     ExtVarNode *evn;
  910.     Var *var;
  911.  
  912.     for (evn = ExtBase; evn; evn = evn->Next) {
  913.     var = evn->Var;
  914.     if ((procs && var->Type->Id == TID_PROC) || (!procs && var->Type->Id != TID_PROC)) {
  915.         if ((var->Flags & TF_EXTERN) && (var->Flags & VF_DECLD) && !(var->Flags & VF_EXTD))
  916.         asm_extern(var);
  917.         if (var->Flags & VF_DECLD)
  918.         var->Flags |= VF_EXTD;
  919.     }
  920.     }
  921. }
  922.  
  923. void
  924. AddStrList(name, len, label, iidx)
  925. ubyte *name;
  926. long len;
  927. long label;
  928. long iidx;
  929. {
  930.     ExtStrNode *esn = AllocStructure(ExtStrNode);
  931.  
  932.     esn->Next = StrBase;
  933.     esn->Str = name;
  934.     esn->Len = len;
  935.     esn->Label = label;
  936.     esn->IIdx = iidx;
  937.  
  938.     /*
  939.      * Internationalizable strings are always constant so we can have a
  940.      * relocation reference and still support residentable code.
  941.      */
  942.  
  943.     if (ConstCode || (iidx >= 0))
  944.     esn->Flags = TF_CONST;
  945.     else
  946.     esn->Flags = 0;
  947.     StrBase = esn;
  948. }
  949.  
  950. void
  951. DelStrList(label)
  952. long label;
  953. {
  954.     ExtStrNode **ep;
  955.  
  956.     for (ep = &StrBase; *ep && (*ep)->Label != label; ep = &(*ep)->Next);
  957.     if (*ep)
  958.     *ep = (*ep)->Next;
  959. }
  960.  
  961. void
  962. DumpStrList()
  963. {
  964.     ExtStrNode *esn;
  965.  
  966.     for (esn = StrBase; esn; esn = esn->Next)
  967.     asm_string(esn->Label, esn->Str, esn->Len, esn->Flags, esn->IIdx);
  968. }
  969.